﻿// 
//    Copyright 2010 The JaernCloud Project
// 
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
// 
//        http://www.apache.org/licenses/LICENSE-2.0
// 
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JaernCloud.Language.Compiler;
using Microsoft.Scripting;
using System.Text.RegularExpressions;
using System.IO;

namespace JaernCloud.Language.Compiler.Ast {

    public class AstTag : AstTokenInfo {

        public static readonly AstTag HTML = new AstTag { Name = "html" };
        public static readonly AstTag VIEW = new AstTag { Name = "view" };
        public static readonly AstTag PAGE = new AstTag { Name = "page" };
        public static readonly AstTag MODEL = new AstTag { Name = "model" };

        public Token Token { get; set; }

        public String Name { get; set; }
        public String Id { get; set; }
        public String Class { get; set; }

        protected AstTag() {

        }

        public static AstTag FromTag(String tag) {
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(tag))) {
                Scanner scanner = new Scanner(ms);
                Token t = scanner.Scan();
                switch (t.kind) {
                    case Parser._tagWithId:
                        return FromWithId(t);
                    case Parser._tagWithClass:
                        return FromWithClass(t);
                    default:
                        return FromIdent(t);
                }
            }
        }

        public static AstTag FromName(String tagName) {
            return new AstTag { Name = tagName };
        }

        public static AstTag FromIdent(Token t) {
            AstTag tag = new AstTag();
            tag.Name = t.val;
            tag.TokenInfo = AstTokenInfo.FromToken(t, TokenCategory.Identifier, TokenTriggers.None);
            return tag;
        }

        public static AstTag FromWithClass(Token t) {
            AstTag tag = new AstTag();
            string[] parts = t.val.Split('.');
            if (parts.Length != 2) {
                throw new ArgumentException(t.val + " is not a valid tag with class");
            }
            tag.Name = parts[0];
            tag.Class = parts[1];
            tag.TokenInfo = AstTokenInfo.FromToken(t, TokenCategory.Identifier, TokenTriggers.None);
            return tag;
        }

        public static AstTag FromWithId(Token t) {
            AstTag tag = new AstTag();
            string[] parts = t.val.Split('#');
            if (parts.Length != 2) {
                throw new ArgumentException(t.val + " is not a valid tag with id");
            }
            tag.Name = parts[0];
            tag.Id = parts[1];
            tag.TokenInfo = AstTokenInfo.FromToken(t, TokenCategory.Identifier, TokenTriggers.None);
            return tag;
        }

        public virtual bool Matches(AstTag tag) {
            bool match = (Name == tag.Name);
            if (match && !String.IsNullOrEmpty(tag.Id)) {
                match = (Id == tag.Id);
            }
            if (match && !String.IsNullOrEmpty(Class)) {
                match = Class == tag.Class;
            }
            return match;
        }

        public override bool Equals(object obj) {
            return obj is AstTag && ToString().Equals(obj.ToString());
        }

        public override int GetHashCode() {
            return ToString().GetHashCode();
        }

        public override string ToString() {
            StringBuilder sb = new StringBuilder();
            sb.Append(Name);
            if (Id != null && Id != String.Empty) {
                sb.Append("#");
                sb.Append(Id);
            }
            if(!String.IsNullOrEmpty(Class)) {
                sb.Append(".");
                sb.Append(Class);
            }
            return sb.ToString();
        }

    }

}
